package com.errol.sync.sync;

import com.renjia.supervise.service.sync.pojo.EntityInfo;
import com.renjia.supervise.service.sync.pojo.SyncAdvisor;

import java.time.LocalDate;

/**
 * @author zhang xiao bin
 * @version v1.0
 * @date 2021/07/02
 * @since v
 **/
public interface DataSyncService {

    /**
     * 由实体类解析类信息和属性（表字段）信息
     * 解析结果缓存，支持并发
     * 如果表字段有特殊需求、或有额外查询参数，可以使用 {@link SyncAdvisor} 注解映射
     *
     * @param entity 实体类
     * @param <E>    实体类型
     * @return 类及属性信息
     */
    <E> EntityInfo<E> getEntityInfo(Class<E> entity);

    /**
     * 由实体类信息生成同步 sql 的 select 子句
     * 如果字段有 {@link SyncAdvisor#fieldNameInSourceDatabase()} 注解且有值，将会查询替代字段、并自动转换为当前表的字段名或属性名
     * 如果字段有 {@link SyncAdvisor#notExistInSourceDatabase()} 注解且值为 true，则注解字段不会拼接入 select 子句
     *
     * @param entityInfo   实体类信息
     * @param useFieldName true 直接使用表字段，false 会添加 as 转为类属性名
     * @param <E>          实体类型
     * @return select 子句
     */
    <E> String generateSelectClause(EntityInfo<E> entityInfo, boolean useFieldName);

    /**
     * 生成 where 子句，根据参数可以是 全量同步、当天或一段日期内的新增数据同步、当天或一段日期内的更新数据同步
     * 如果实体类有 {@link SyncAdvisor#additionalWhereClause()} 注解且有值，将会作为额外的查询参数自动添加
     *
     * @param <E>          实体类型
     * @param entityInfo   表信息
     * @param rangeLeft    null 生成全量更新的 where 子句，非空则生成当天或一段日期内的数据同步的 where 子句
     * @param rangeRight   非空则以 rangeLeft 为左区间、rangeRight 为右区间，生成 where 子句，两者都包含
     * @param queryNewData true 生成当天新增数据同步的 where 子句，false 生成当天更新数据（包含被删除的）同步的 where 子句
     * @return where 子句
     */
    <E> String generateWhereClause(EntityInfo<E> entityInfo, LocalDate rangeLeft, LocalDate rangeRight, boolean queryNewData);

    /**
     * 同步全量数据
     *
     * @param <E>         实体类型
     * @param entityClass 实体类
     * @return 提示信息，或 null 表示成功
     */
    <E> String syncData(Class<E> entityClass);

    /**
     * 同步单天数据
     *
     * @param <E>              实体类型
     * @param entityClass      实体类
     * @param syncDate         执行增量同步
     * @param updateEditedData true 在增量同步新增数据的同时，额外同步当天更新的数据
     * @return 提示信息，或 null 表示成功
     */
    <E> String syncData(Class<E> entityClass, LocalDate syncDate, boolean updateEditedData);

    /**
     * 同步一段日期内的数据，由调用者保证 rangeLeft < rangeRight
     *
     * @param <E>              实体类型
     * @param entityClass      实体类
     * @param rangeLeft        日期区间左边界，包含
     * @param rangeRight       日期区间右边界，包含
     * @param updateEditedData true 在增量同步新增数据的同时，额外同步当天更新的数据
     * @return 提示信息，或 null 表示成功
     */
    <E> String syncData(Class<E> entityClass, LocalDate rangeLeft, LocalDate rangeRight, boolean updateEditedData);

}
